package com.wenhui.lib.scrollableslidinguppanelayout; import android.content.Context; import android.support.v4.view.MotionEventCompat; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; import com.wenhui.lib.scrollableslidinguppanelayout.ScrollableSlidingUpPaneLayout.PanelSlideListenerInternal; public class ScrollableSlidingUpPaneLayoutHelper implements View.OnTouchListener { private int mTouchSlop; private int mInitialY = -1; private ViewDelegate mViewDelegate; private ViewGroup mTargetView; private ScrollableSlidingUpPaneLayout mSlidingLayout; private boolean mIsReadyToPullChecked = false; static ScrollableSlidingUpPaneLayoutHelper getInstance(Context context){ return new ScrollableSlidingUpPaneLayoutHelper(context); } protected ScrollableSlidingUpPaneLayoutHelper(Context context){ mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); } public void addScrollableView(ScrollableSlidingUpPaneLayout layout, ViewGroup view){ mTargetView = view; mViewDelegate = InstanceCreationUtils.getBuiltInViewDelegate(mTargetView); if (mViewDelegate == null) { throw new IllegalArgumentException( "No view handler found. Please provide one."); } mTargetView.setOnTouchListener(this); mSlidingLayout = layout; mSlidingLayout.setPanelExpandedListener(mPanelExpandedListener); } @Override public boolean onTouch(View v, MotionEvent event) { final int action = MotionEventCompat.getActionMasked(event); if( mTargetView instanceof SlideableScrollView && ((SlideableScrollView) mTargetView).isReadyForPull(mTargetView, event.getX(), event.getY()) && !mIsReadyToPullChecked ){ // ScrollView will skip Action_down event, this is to fix this problem mInitialY = ( (SlideableScrollView)mTargetView ).mInitialY; } switch (action) { case MotionEvent.ACTION_DOWN: if (mViewDelegate.isReadyForPull(v, event.getX(), event.getY())) { mInitialY = (int) event.getY(); } break; case MotionEvent.ACTION_MOVE: if (mInitialY > 0) { int yDiff = mInitialY - (int) event.getY(); if ( yDiff < mTouchSlop ) { enableSlidingPane(); resetTouch(); } } break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: resetTouch(); } return false; } private void resetTouch() { mInitialY = -1; mIsReadyToPullChecked = false; } private void enableSlidingPane() { mTargetView.requestDisallowInterceptTouchEvent(true); mSlidingLayout.setSlidingEnabled(true); mSlidingLayout.requestDisallowInterceptTouchEvent(false); } private void disableSlidingPane() { mTargetView.requestDisallowInterceptTouchEvent(false); mSlidingLayout.setSlidingEnabled(false); mSlidingLayout.requestDisallowInterceptTouchEvent(true); } private PanelSlideListenerInternal mPanelExpandedListener = new PanelSlideListenerInternal() { @Override public void onPanelExpandedInternal() { disableSlidingPane(); } @Override public void onPanelCollapseInternal() { enableSlidingPane(); } }; /** * ViewDelegates are what are used to de-couple the Attacher from the different types of * scrollable views. */ public static interface ViewDelegate { /** * Allows you to provide support for View which do not have built-in * support. In this method you should cast <code>view</code> to it's * native class, and check if it is scrolled to the top. * * @param view * The view which has should be checked against. * @param x The X co-ordinate of the touch event * @param y The Y co-ordinate of the touch event * @return true if <code>view</code> is scrolled to the top. */ public boolean isReadyForPull(View view, float x, float y); } }